package com.wyh.utils.g3utils;

import com.wyh.common.utils.DateUtils;
import com.wyh.domain.dto.g3dto.G3OrganizationDto;
import javafx.util.Pair;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URLEncoder;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

@Slf4j
public class ProjectUtils {
    //验证部分是否为空
    public static boolean isPartEmpty(Object obj) {
        if (obj == null) {
            return false;
        }
        //拿到对象里的字节码对象
        Class<?> aClass = obj.getClass();

        //通过字节码对象获取所有字段
        Field[] fields = aClass.getFields();

        for (Field field : fields) {
            //设置私有属性也可以访问
            field.setAccessible(true);
            try {
                Object o = field.get(obj);
                if (o == null){
                    return true;
                }
            } catch (IllegalAccessException e) {
               throw new RuntimeException("反射获取属性值失败"+field.getName(),e);
            }
        }
        return false;
    }
    //全部是否为空
    public static boolean isAllNotEmpty(Object obj) {
        if (obj == null) {
            return false;
        }
        Class<?> aClass = obj.getClass();
        Field[] fields = aClass.getFields();
        for (Field field : fields) {
            field.setAccessible(true);
            try {
                Object o = field.get(obj);
                if (o == null){
                    //判断field的类型,如果是Integer就赋值为0
                    if (field.getType().equals(Integer.class)) {
                        field.set(obj,0);
                    }else if (field.getType().equals(Double.class)){
                        field.set(obj,0.0);
                    }
                    return false;
                }
            } catch (IllegalAccessException e) {
                throw new RuntimeException("反射获取属性值失败"+field.getName(),e);
            }
        }
        return true;
    }
    //计算收费率
    public static Double calculateFeePercentage(Double currentFee, Double allFee) {
        if (currentFee > allFee) {
            throw new RuntimeException("当前费用不能大于总费用");
        }
        if (allFee == 0.0) {
            return 0.0;
        }

        Double value = currentFee/allFee*100;
        Double result = keepTwoDecimalPlaces(value);
        return result;
    }

    //计算月环比
    public static Double calculateMonthRatio(Double currentMonthValue, Double lastMonthValue) {

        if (lastMonthValue == null || lastMonthValue == 0) {
            return 0.0;
        }
        Double result = 0.0;
        if (currentMonthValue <= lastMonthValue) {
            result = lastMonthValue - currentMonthValue;
        } else if (currentMonthValue > lastMonthValue) {
            result = currentMonthValue - lastMonthValue;
        }
        result = result / lastMonthValue * 100;
        return result;
    }
    //时间封装
    public static void encapsulationTime(G3OrganizationDto g3OrganizationDto) {
        //将实体里时间封装进去

        //1.1 获取当前时区的ZonedDateTime
        ZonedDateTime now = ZonedDateTime.now(ZoneId.systemDefault());
        //1.2先获取本月结束的时间(也就是当前时间)
        String date = DateUtils.getTime();
        g3OrganizationDto.setCurrentMonthEndTime(date);
        // 2.1获取本月的第一天（开始时间）
        LocalDate firstDayOfMonth = LocalDate.of(now.getYear(), now.getMonth(), 1);
        LocalDateTime startOfMonthDateTime = firstDayOfMonth.atStartOfDay();

        g3OrganizationDto.setCurrentMonthStartTime(startOfMonthDateTime.toString());
        //3.1获取上一月的开始时间
        LocalDate lastMonthFirstDay = firstDayOfMonth.minusMonths(1);
        LocalDateTime lastMonthStartOfMonthDateTime = lastMonthFirstDay.atStartOfDay();

        g3OrganizationDto.setLastMonthStartTime(lastMonthStartOfMonthDateTime.toString());

        //3.2获取上一月的结束时间

        LocalDate lastMonthLastDay = lastMonthFirstDay.withDayOfMonth(lastMonthFirstDay.lengthOfMonth());

        LocalDateTime localDateTime = lastMonthLastDay.atStartOfDay();
        LocalDateTime localCurrentDateTime = localDateTime.withHour(23).withMinute(59).withSecond(59);
        g3OrganizationDto.setLastMonthEndTime(localCurrentDateTime.toString());

        //3.3获取上一年的同一个月的开始时间
        LocalDateTime lastYearFirstDay = startOfMonthDateTime.minusYears(1);
        g3OrganizationDto.setLastMonthStartTimeYoY(lastYearFirstDay.toString());

        //3.4获取上一年的同一个月的结束时间
        DateTimeFormatter customFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        LocalDateTime lastYearLastDay = LocalDateTime.parse(date, customFormatter);
        LocalDateTime  localDateTime1 = lastYearLastDay.minusYears(1).withDayOfMonth(lastYearLastDay.toLocalDate().lengthOfMonth());
        LocalDateTime lastCurrentYearLastDay  = localDateTime1.withHour(23).withMinute(59).withSecond(59);
        g3OrganizationDto.setLastMonthEndTimeYoY(lastCurrentYearLastDay.toString());
    }
    //验证前段发送的时间是否正确
    public static void checkTime(G3OrganizationDto g3OrganizationDto, String beginTime, String endTime) {
        LocalDate now = LocalDate.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        //如果开始时间和结束时间相等,那就说明前端发送的时间是同一天,
        if (StringUtils.normalizeSpace(beginTime).equals(StringUtils.normalizeSpace(endTime))) {
            log.info("开始时间和结束时间相等,准备区分两个时间");
            //将开始时间的时分秒设置为00:00:00,

            LocalDate parse = LocalDate.parse(beginTime, formatter);
            LocalDateTime localDateTime = parse.atStartOfDay();
            g3OrganizationDto.setBeginTime(localDateTime.toString());
            log.info("开始时间的时分秒设置为00:00:00");
            // 结束时间的年月日和当前时间进行比对,如果是同一天,那就把当前时间的时分秒加到结束时间上
            if (beginTime.equals(now.toString())) {
                LocalDateTime end = LocalDateTime.now();
                g3OrganizationDto.setEndTime(end.toString());
                log.info("结束时间的年月日和当前时间是同一天,将时间设置为现在");
            } else {
                //如果不是同一天,那就把结束时间设置为23:59:59
                g3OrganizationDto.setEndTime(localDateTime.withHour(23).withMinute(59).withSecond(59).toString());
                log.info("结束时间的年月日和当前时间不是同一天,结束时间设置为23:59:59");
            }
        }
    }

    public static Double keepTwoDecimalPlaces(Double value) {
        BigDecimal bd = new BigDecimal(value);
        double result = bd.setScale(2, RoundingMode.HALF_UP).doubleValue();
        return result;
    }
    public static void setExcelResponseProp(HttpServletResponse response, String rawFileName) throws UnsupportedEncodingException, UnsupportedEncodingException, UnsupportedEncodingException {
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        String fileName = URLEncoder.encode(rawFileName, "UTF-8").replaceAll("\\+", "%20");
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
    }

    /**
     * 对List进行分页处理
     * @param list 原始数据列表
     * @param pageNumber 当前页码
     * @param pageSize 每页大小
     * @return 分页后的数据及总页数
     */
    public static <T> Pair<List<T>, Integer> paginate(List<T> list, int pageNumber, int pageSize) {
        if (list == null || list.isEmpty()) {
            return new Pair<>(Collections.emptyList(), 0);
        }

        // 计算总页数
        int totalElements = list.size();
        int totalPages = (totalElements + pageSize - 1) / pageSize;

        // 验证页码是否合法
        if (pageNumber < 1) {
            pageNumber = 1;
        } else if (pageNumber > totalPages) {
            pageNumber = totalPages;
        }

        // 计算分页起始位置
        int startIndex = (pageNumber - 1) * pageSize;

        // 分页处理
        List<T> paginatedList = new ArrayList<>(pageSize);
        for (int i = startIndex; i < Math.min(startIndex + pageSize, totalElements); i++) {
            paginatedList.add(list.get(i));
        }

        return new Pair<>(paginatedList, totalElements);
    }
}

